import { Injector } from '@angular/core';
import { MessagerService } from '@farris/ui-messager';
import { NotifyService } from '@farris/ui-notify';
import { EventEditorService, DomService, RefreshFormService, FormTempateOutlineSchema } from '@farris/designer-services';
import { DgControl } from '../../../../../utils/dg-control';
import { ControlContextMenuItem } from '../../../../../entity/control-context-menu';
import { ControlService } from '../../../../../service/control.service';
import { FarrisDesignBaseComponent } from '@farris/designer-element';


const DATAGRID_MULTI_VIEW_COMMAND = 'MultiViewContainer';

/**
 * 列表启用/移除多视图相关服务
 */
export class DataGridMultiViewContextMenuService {

    /** 列表组件Ref节点的父节点 */
    gridRefParentNode: any;
    private eventEditorService: EventEditorService;
    private domService: DomService;
    private messagerService: MessagerService;
    public refreshFormService: RefreshFormService;
    private notifyService: NotifyService;
    private controlService: ControlService;

    constructor(
        private injector: Injector) {
        this.domService = this.injector.get(DomService);
        this.eventEditorService = this.injector.get(EventEditorService);
        this.notifyService = this.injector.get(NotifyService);
        this.refreshFormService = this.injector.get(RefreshFormService);
        this.controlService = this.injector.get(ControlService);
        this.messagerService = this.injector.get(MessagerService);
    }

    /**
     * 组装多视图菜单项
     * @param menuConfig 多视图菜单
     * @param dataGridId 列表id
     * @param componentId 列表所属组件id
     */
    assembleMultiViewMenu(menuConfig: ControlContextMenuItem[], dataGridId: string, componentId: string) {
        const multiViewMenu = menuConfig.find(menu => menu.id === DATAGRID_MULTI_VIEW_COMMAND);
        if (!multiViewMenu) {
            return menuConfig;
        }
        // 若检测到模板schema配置节，则根据配置节中是否包含多视图配置节来判断；若没有检测到配置节，则默认允许启用多视图
        const templateOutlineSchema = this.domService.templateOutlineSchema || [];
        const dataGridSchemaItem = this.findOutlineSchemaNodeByControlId(templateOutlineSchema, dataGridId, componentId);
        if (dataGridSchemaItem && (!dataGridSchemaItem.multiView || !dataGridSchemaItem.multiView.canEnable)) {
            menuConfig = menuConfig.filter(menu => menu.id !== DATAGRID_MULTI_VIEW_COMMAND);
            return menuConfig;
        }

        // 双列表标签页模板，不支持启用多视图
        if (this.domService && this.domService.module && this.domService.module.templateId === 'double-list-in-tab-template') {
            menuConfig = menuConfig.filter(menu => menu.id !== DATAGRID_MULTI_VIEW_COMMAND);
            return menuConfig;
        }

        const rootCmp = this.domService.getComponentById('root-component');
        const nodeInfo = this.domService.selectNodeAndParentNode(rootCmp, item => item.type === DgControl.ComponentRef.type && item.component === componentId, rootCmp);
        this.gridRefParentNode = nodeInfo.parentNode;

        if (this.gridRefParentNode.type === DgControl.MultiViewItem.type) {
            multiViewMenu.title = '移除多视图';
            multiViewMenu.id = 'remove' + multiViewMenu.id;
        } else {
            multiViewMenu.title = '启用多视图';
            multiViewMenu.id = 'enable' + multiViewMenu.id;
        }

        return menuConfig;
    }


    /**
     * 根据控件所属组件id判断控件在schema中所属的区域
     * @param controlId 控件id
     */
    private findOutlineSchemaNodeByControlId(outlineSchema: FormTempateOutlineSchema[], controlId: string, componentId: string) {
        if (!outlineSchema || outlineSchema.length === 0) {
            return;
        }

        for (const schemaItem of outlineSchema) {

            if (schemaItem.children && schemaItem.children.length > 0) {
                const item = this.findOutlineSchemaNodeByControlId(schemaItem.children, controlId, componentId);
                if (item) {
                    return item;
                }
            }
            if (schemaItem.type !== 'DataGrid') {
                continue;
            }
            const rootCmp = this.domService.getComponentById('root-component');
            if (typeof (schemaItem.path) === 'object' && schemaItem.path.length) {
                for (const path of schemaItem.path) {
                    const containerNode = this.domService.getNodeByIdPath(rootCmp, path);
                    const gridCmpRefNode = this.domService.selectNode(containerNode,
                        item => item.type === DgControl.ComponentRef.type && item.component === componentId);
                    if (gridCmpRefNode) {
                        return schemaItem;
                    }
                }
            } else {
                if (schemaItem.isGridCollection) {
                    const containerNodes = this.domService.getNodesByIdPath(rootCmp, schemaItem.path as string);
                    for (const containerNode of containerNodes) {
                        const gridCmpRefNode = this.domService.selectNode(containerNode,
                            item => item.type === DgControl.ComponentRef.type && item.component === componentId);
                        if (gridCmpRefNode) {
                            return schemaItem;
                        }
                    }

                } else {
                    const containerNode = this.domService.getNodeByIdPath(rootCmp, schemaItem.path as string);
                    const gridCmpRefNode = this.domService.selectNode(containerNode,
                        item => item.type === DgControl.ComponentRef.type && item.component === componentId);
                    if (gridCmpRefNode) {
                        return schemaItem;
                    }
                }

            }
        }
    }

    /**
     * 启用多视图
     * @param viewModelId 视图模型id
     * @param dataSource 绑定数据源
     */
    enableMultiViewContainer(viewModelId: string, dataGrid: any) {
        this.enableGridMultiView(this.gridRefParentNode, viewModelId, dataGrid);

        // 刷新页面
        this.refreshFormService.refreshFormDesigner.next();
        this.notifyService.success('启用成功');
    }

    /**
     * 移除多视图
     */
    removeMultiViewContainer(cmpInstance: FarrisDesignBaseComponent) {

        this.messagerService.question('确定移除多视图？', () => {
            this.removeGridMultiView(this.gridRefParentNode);

            cmpInstance.emit('clearPropertyPanel');

            // 刷新页面
            this.refreshFormService.refreshFormDesigner.next();
            this.notifyService.success('已移除多视图');
        });

    }


    /**
     * 启用多视图
     * @param componentContainer 列表组件ComponentRef节点的父容器
     * @param viewModelId 列表组件所在ViewModelId
     * @param dataSource 列表组件数据源
     */
    private enableGridMultiView(componentContainer: any, viewModelId: string, dataGrid: any) {

        const radomNum = Math.random().toString().slice(2, 6);
        const dataGridComponentRefIndex = componentContainer.contents.findIndex(co => co.type === DgControl.ComponentRef.type);
        const dataGridComponentRef = componentContainer.contents[dataGridComponentRefIndex];
        const dataridViewModel = this.domService.getViewModelById(viewModelId);
        const multiviewContainer = this.controlService.getControlMetaData(DgControl.MultiViewContainer.type);
        const dataGridMultiviewItem = this.controlService.getControlMetaData(DgControl.MultiViewItem.type);
        const viewChange = this.controlService.getControlMetaData(DgControl.ViewChange.type);

        // 创建多视图组件
        let multiViewContainerClass = '';
        if (dataridViewModel.bindTo === '/') {
            multiViewContainerClass += 'f-utils-fill-flex-column';
        }
        if (dataGrid.isChildFill) {
            multiViewContainerClass += ' f-multiview-fill'; // 子表启用容器填充
        }
        Object.assign(multiviewContainer, {
            id: `${componentContainer.id}-multiview`,
            appearance: {
                class: multiViewContainerClass
            },
            contents: [dataGridMultiviewItem],
            viewGroupIdentify: componentContainer.id,
            defaultType: `viewItem_${radomNum}`,
            dataSource: dataGrid.dataSource
        });


        // 创建多视图项，存放原datagrid 组件引用节点
        const multiViewClass = dataridViewModel.bindTo === '/' ?
            'f-viewchange-content-item f-utils-fill-flex-column' : 'f-viewchange-content-item';
        Object.assign(dataGridMultiviewItem, {
            id: `viewItem_${radomNum}`,
            appearance: {
                class: multiViewClass
            },
            title: `表格视图`,
            icon: 'f-icon f-icon-table_view',
            contents: [dataGridComponentRef]
        });

        // 创建视图切换图标组件
        Object.assign(viewChange, {
            id: `${componentContainer.id}-viewchange`,
            appearance: {
                class: 'f-btn-ml'
            },
            defaultType: `viewItem_${radomNum}`,
            toolbarData: [
                {
                    type: `viewItem_${radomNum}`,
                    title: `表格视图`,
                    iconName: 'f-icon f-icon-table_view'
                }
            ],
            viewGroupIdentify: componentContainer.id
        });

        componentContainer.contents[dataGridComponentRefIndex] = multiviewContainer;

        // 在标签页中追加多视图属性
        if (componentContainer.type === DgControl.TabPage.type || componentContainer.type === DgControl.Section.type) {
            viewChange.viewType = 'tile';
            componentContainer.multiViews = true;
            componentContainer.views = viewChange;
        }

        // 在表单header容器中追加多视图组件
        if (componentContainer.type === DgControl.ContentContainer.type) {
            const componentContainerAppearance = componentContainer.appearance || {};
            const componentContainerClass: string = componentContainerAppearance.class || '';
            if (componentContainerClass.indexOf('f-page-main') > -1) {
                const rootComponentElement = this.domService.getComponentById('root-component');
                const { pageHeaderElement, path } = this.findPageHeaderElement(rootComponentElement);
                if (pageHeaderElement) {
                    this.updatePageHeader(pageHeaderElement, viewChange, multiviewContainer, path);
                }
            }
        }

    }
    /**
     * 关闭多视图
     * @param componentContainer 列表组件ComponentRef节点的父容器，多视图状态下父容器是MultiViewItem
     */
    private removeGridMultiView(componentContainer: any) {
        const rootComponentElement = this.domService.getComponentById('root-component');

        const multiviewItemElement = componentContainer;
        let gridComponentRefElement = null;
        let gridComponentRefElementIndex;
        if (multiviewItemElement && multiviewItemElement.contents && multiviewItemElement.contents.length) {
            gridComponentRefElementIndex = multiviewItemElement.contents.findIndex(co => co.type === DgControl.ComponentRef.type);
            gridComponentRefElement = multiviewItemElement.contents[gridComponentRefElementIndex];
        }

        const multiviewInfo = this.domService.selectNodeAndParentNode(rootComponentElement,
            (item) =>
                item.type === DgControl.MultiViewContainer.type && item.contents && item.contents.find(i => i.id === componentContainer.id)
            , null);
        if (!multiviewInfo) {
            return;
        }
        // 多视图组件节点
        const multiviewContainerElement = multiviewInfo.node;
        // 多视图组件的父节点，用于存放DataGrid ComponentRef节点
        const componentContainerElement = multiviewInfo.parentNode;

        if (componentContainerElement && gridComponentRefElement) {
            const index = componentContainerElement.contents.findIndex(element => element.id === multiviewContainerElement.id);
            componentContainerElement.contents.splice(index, 1, ...multiviewItemElement.contents);

            // 移除标签页下的viewChange按钮
            if (componentContainerElement.type === DgControl.TabPage.type || componentContainerElement.type === DgControl.Section.type) {
                if (componentContainerElement.multiViews) {
                    componentContainerElement.multiViews = false;
                }
                if (componentContainerElement.views) {
                    componentContainerElement.views = {};
                }
            }
        }

        // 移除header区域viewChagne按钮
        let viewChangeElement;
        if (multiviewContainerElement && multiviewContainerElement.viewChangeBar && gridComponentRefElement) {
            // componentContainerElement.contents = [gridComponentRefElement];
            const rootComponentJson = this.domService.getComponentById('root-component');
            viewChangeElement = this.domService.getNodeByIdPath(rootComponentJson, multiviewContainerElement.viewChangeBar);
            const headerToolbarContainer = this.domService.domDgMap.get('header-nav');

            headerToolbarContainer.contents = headerToolbarContainer.contents.filter(co => co.id !== viewChangeElement.id);
        }

        multiviewContainerElement.contents.forEach(multiViewItem => {
            this.removeRedundantNodeInMultiViewItem(multiViewItem, gridComponentRefElement.id);
        });

        return componentContainerElement;
    }

    /**
     * 多视图项中若包含除DataGrid ComponentRef节点外的其他componentRef或ExternalContainer，则需要删除组件节点和外部组件的声明节点
     * @param multiviewContainerElement 多视图组件节点
     */
    private removeRedundantNodeInMultiViewItem(multiViewItem: any, gridComponentRefElementId: string) {


        // 删除组件节点和viewModel节点
        const cmpRefNode = this.domService.selectNode(multiViewItem,
            (item) => item.type === DgControl.ComponentRef.type && item.id !== gridComponentRefElementId);
        if (cmpRefNode) {
            const cmp = this.domService.getComponentById(cmpRefNode.component);
            if (cmp) {
                this.domService.deleteComponent(cmp.id);
                this.domService.deleteViewModelById(cmp.viewModel);
            }
        }

        // 删除外部组件的声明节点和订阅节点
        const externalContainerNode = this.domService.selectNode(multiViewItem,
            (item) => item.type === DgControl.ExternalContainer.type);
        if (externalContainerNode && externalContainerNode.externalCmp) {
            this.domService.deleteExternalComponent(externalContainerNode.externalCmp);
            this.deleteComponentSubscription(externalContainerNode.externalCmp);
        }


    }
    private deleteComponentSubscription(cmpId: string) {
        const subscriptions = this.domService.module.subscriptions;
        if (subscriptions && subscriptions.length) {
            this.domService.module.subscriptions = subscriptions.filter(
                (item) => item.sourceComponent !== cmpId && item.targetComponent !== cmpId
            );
        }

    }
    /**
     * 定位页头  （TODO：页头有header容器和header组件两种可能）
     * @param rootComponentElement 根组件
     */
    private findPageHeaderElement(rootComponentElement): { pageHeaderElement: any, path: string } {
        const rootLayoutElement = rootComponentElement.contents[0];
        let pageHeaderElement = rootLayoutElement.contents.find((element) => element.id === 'page-header');
        if (pageHeaderElement) {
            const path = 'root-layout.page-header';
            return { pageHeaderElement, path };
        } else {
            const rootLayoutContentElement = rootLayoutElement.contents.find((element) => element.id === 'root-layout-content');
            if (rootLayoutContentElement) {
                const pageContentElement = rootLayoutContentElement.contents.find((element) => element.id === 'page-content');
                if (pageContentElement) {
                    const pageContentMainElement = pageContentElement.contents.find((element) => element.id === 'page-content-main');
                    if (pageContentMainElement) {
                        const pageContentLayoutElement = pageContentMainElement.contents
                            .find((element) => element.id === 'page-content-layout');
                        if (pageContentLayoutElement) {
                            pageHeaderElement = pageContentLayoutElement.contents.find((element) => element.id === 'page-header');
                            if (pageHeaderElement) {
                                // tslint:disable-next-line:max-line-length
                                const path = 'root-layout.root-layout-content.page-content.page-content-main.page-content-layout.page-header';
                                return { pageHeaderElement, path };
                            }
                        }
                    }
                }
            }
        }
    }

    private updatePageHeader(pageHeaderElement: any, viewChange: any, multiviewContainer: any, pathHeaderPath: string) {
        if (pageHeaderElement.type === DgControl.ContentContainer.type) {
            const pageHeaderNavElement = pageHeaderElement.contents.find((element) => element.id === 'header-nav');
            if (pageHeaderNavElement) {
                const pageHeaderNavElementContents: any[] = pageHeaderNavElement.contents || [];
                const toolbarElementIndex = pageHeaderNavElementContents.findIndex(
                    (element: any) => element.type === DgControl.ToolBar.type);
                if (toolbarElementIndex > -1) {
                    const toolbarElement = pageHeaderNavElementContents[toolbarElementIndex];
                    Object.assign(toolbarElement, {
                        appearance: {
                            class: 'col-7 f-toolbar ml-auto'
                        }
                    });
                }
                pageHeaderNavElementContents.push(viewChange);

                // 在多视图组件中记录viewChange图标的路径
                const path = `${pathHeaderPath}.header-nav.${viewChange.id}`;
                multiviewContainer.viewChangeBar = path;
            }
        } else if (pageHeaderElement.type === DgControl.Header.type) {

        }

    }
}
